<?php

namespace App\Notifications\Train\TrainOrder;

use App\Facades\Sms;
use App\Models\Train\TrainOrderPassengers\TrainOrderPassenger;
use App\Models\Train\TrainOrders\TrainOrder;
use App\Models\Train\TrainOrderTrain\TrainOrderTrain;
use App\Models\User\Repositories\Interfaces\UserRepositoryInterface;
use App\Models\User\User;
use App\Trip\Notify\Channel\SmsChannel;
use App\Trip\Notify\Channel\TcccChannel;
use App\Trip\Notify\Channel\WechatMiniAppChannel;
use App\Trip\Notify\Channel\WechatOfficialChannel;
use App\Trip\Notify\Sms\Messages\Train\SnapSuccessNotifyMessage;
use App\Trip\Tencent\Cloud\SDK\TCCC\Tccc;
use App\Trip\Train\Seat\TrainPassengerSeat;
use App\Trip\Wechat\Account\WechatMiniAppLogin;
use App\Trip\Wechat\Account\WechatOfficialLogin;
use Carbon\Carbon;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;

class SnapSuccessNotify extends Notification
{
    use Queueable;


    private TrainOrder      $order;
    private ?User           $user;
    private TrainOrderTrain $train;
    /**
     * @var TrainOrderPassenger[]|Collection
     */
    private array|Collection $passengers;

    /**
     * Create a new notification instance.
     *
     * @return void
     */

    public function __construct(TrainOrder $order)
    {
        $this->order      = $order;
        $userRepo         = app(UserRepositoryInterface::class);
        $this->user       = $userRepo->getUserByUserId($this->order->getUserId());
        $this->train      = $this->order->getMainTrain();
        $this->passengers = $this->order->passengers;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param mixed $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [SmsChannel::class, WechatMiniAppChannel::class, WechatOfficialChannel::class, TcccChannel::class];
    }

    /**
     * 获取短信通知。
     *
     * @param mixed $notifiable
     *
     * @throws Exception
     */
    public function toSms($notifiable)
    {
        try {
            $message = new SnapSuccessNotifyMessage($this->order);
            Sms::send($this->order->getMobile(), $message);
        } catch (Exception $e) {
            Log::error("抢票成功,短信发送失败:{$e->getMessage()},{$this->order->getOrderSn()}");
        }
    }

    /**
     * 获取语音通知。
     *
     * @param mixed $notifiable
     *
     * @throws Exception
     */
    public function toTccc($notifiable)
    {
        if ($this->order->isSnapUp()) {
            $tccc        = new Tccc();
            $business_id = config('qcloud.tccc.business.train_snap_success');
            if ($business_id) {
                $mobile = $this->order->getMobile();
                $tccc->createAutoCalloutTask([
                    'business_id' => $business_id,
                    'mobile'      => $mobile,
                ]);
            }
        }
    }


    /**
     * 获取微信小程序通知。
     *
     * @param mixed $notifiable
     *
     */
    public function toWechatMiniApp($notifiable)
    {
        $user = $this->user?->getMiniAppUser();
        if (!$user) {
            Log::info("抢票成功，我发微信小程序订阅消息未找到用户,{$this->order->getOrderSn()}");
        }
        $config = config('weixin.miniapp')['message']['subscribes'] ?? [];
        if (empty($config)) {
            Log::info("抢票成功，我发微信小程序订阅消息未找到配置文件,{$this->order->getOrderSn()}");
            return;
        }

        $collect     = collect($config)->where('type', 'train_order_snap_success');
        $template_id = $collect->value('template_id');
        $msg         = [
            "touser"            => $user->getOpenId(),
            "template_id"       => $template_id,
            "page"              => "pages/order/order",
            "miniprogram_state" => "developer",
            "lang"              => "zh_CN",
            "data"              => [
                'thing1' => [
                    'value' => __("抢票成功"),
                ],
                'thing4' => [
                    'value' => $this->order->getTrainCode().'|'.Str::limit("{$this->train->getFromName()} -> {$this->train->getToName()}", 80, ""),//$this->order->getTrainCode().'|'.Str::limit("{$this->train->getFromNameUy()} -> {$this->train->getToNameUy()}", 80, ""),
                ],
                'thing7' => [
                    'value' => Str::limit("{$this->train->getFromName()} -> {$this->train->getToName()}", 80, ""),
                ],
                'date3'  => [
                    'value' => Carbon::parse($this->order->getTrainDate())->format("Y年m月d日 H:i"),// Carbon::parse($this->order->getTrainDate())->format("Y-".__('年')."m-".__('月')."d-".__('日')." H:i"),// 年月日时分
                ],
                'thing8' => [
                    'value' => __("抢票成功，请登录小程序查看详情"), // 出票结果
                ],
            ],
        ];

        if (empty($msg)) {
            return;
        }


        $w       = new WechatMiniAppLogin();
        $app     = $w->application();
        $client  = $app->getClient();
        $content = $client->postJson('/cgi-bin/message/subscribe/send', $msg);
        Log::info("抢票成功，微信小程序订阅消息:".$content->getContent()."-{$this->order->getOrderSn()}");

    }

    /**
     * 获取微信公众号通知。
     *
     * @param mixed $notifiable
     *
     * @throws TransportExceptionInterface
     */
    public function toWechatOfficial($notifiable)
    {
        $user = $this->user?->getOfficialUser();
        if ($user?->isSubscribe() == 1) {
            $mini_user = $this->user->getMiniAppUser();
            // TODO 根据 user de appid 进行通知
            $config = config('weixin.officials')[0]['message']['templates'] ?? [];
            if (empty($config)) {
                Log::info("我发微信 模板消息未找到配置文件,{$this->order->getOrderSn()}");
                return;
            }
            $pss         = collect($this->passengers)->map(function ($passenger) {
                return TrainPassengerSeat::seatNoDesc($passenger);
            });
            $collect     = collect($config)->where('type', 'train_order_snap_success');
            $template_id = $collect->value('template_id');
            $train_date  = Carbon::parse($this->order->getTrainDate())->format("Y-".__('年')."m-".__('月')."d-".__('日'));
            $msg         = [
                "touser"      => $user->getOpenId(),
                "template_id" => $template_id,
                "miniprogram" => [
                    "appid"    => $mini_user->getAppId(),
                    "pagepath" => "pages/order/order",
                ],
                "topcolor"    => "#FF0000",
                "data"        => [
                    "first"    => [
                        "value" => "抢票成功啦",
                        "color" => "#173177",
                    ],
                    'keyword1' => [
                        'value' => $this->order->ticket_number,
                    ],
                    'keyword2' => [
                        'value' => $this->order->getTrainCode(),
                    ],
                    'keyword5' => [
                        'value' => Carbon::parse($this->order->getTrainDate())->format("Y-m-d H:i"),// 月日时分
                    ],
                    'keyword3' => [
                        'value' => Str::limit("{$this->train->getFromNameUy()} -> {$this->train->getToNameUy()}", 80, ""),
                    ],
                    'keyword4' => [
                        'value' => Str::limit($pss->implode(' '), 80, ''),
                    ],
                    'remark'   => [
                        'value' => '高铁管家提醒您，仔细检查车票信息，如需退票/改签，请登录小程序操作。',
                    ],
                ],
            ];

            if (empty($msg)) {
                return;
            }


            $w            = new WechatOfficialLogin();
            $official_app = $w->application();
            $client       = $official_app->getClient();
            $content      = $client->postJson('/cgi-bin/message/template/send', $msg);
            Log::info("抢票成功，微信模板消息:".$content->getContent()."-{{$this->order->getOrderSn()}}");
        } else {
            Log::info("抢票成功，我发微信 模板消息未关注公众号,{$this->order->getOrderSn()}");
        }
    }

}
